#pragma once
#include <functional>

#include "ActionGroup.hpp"
#include "PoseHandler.hpp"
namespace adas
{

class MoveCommand final
{
public:

    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
    {
        ActionGroup actionGroup;
        const auto action =poseHandler.IsReverse() ? ActionType::BACKWARD_1_STEP_ACTION : ActionType::FORWARD_1_STEP_ACTION;
        switch (poseHandler.carType) {
            case CarsType::CAR:
                if (poseHandler.IsFast()) actionGroup.PushAction(action);
                actionGroup.PushAction(action);
                break;
            case CarsType::SPORTS_CAR:
                if(poseHandler.IsFast()){
                    actionGroup.PushAction(action);
                    actionGroup.PushAction(action);
                }actionGroup.PushAction(action);
                actionGroup.PushAction(action);
                break;
            case CarsType::BUS:
                if(poseHandler.IsFast())actionGroup.PushAction(action);
                actionGroup.PushAction(action);
                break;
            default:
                break;
    }return actionGroup;
    }
};

class TurnLeftCommand final
{
public:
    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
    {
        ActionGroup actionGroup;
        const auto action =poseHandler.IsReverse() ? ActionType::BACKWARD_1_STEP_ACTION : ActionType::FORWARD_1_STEP_ACTION;
        const auto turnAction =poseHandler.IsReverse() ? ActionType::REVERSE_TURNLEFT_ACTION : ActionType::TURNLEFT_ACTION;
        switch (poseHandler.carType) {
        case CarsType::CAR:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            break;
        case CarsType::SPORTS_CAR:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            actionGroup.PushAction(action);
            break;
        case CarsType::BUS:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            break;
        default:
            break;
        }
        return actionGroup;
    }
};

class TurnRightCommand final
{
public:
    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
    {
        ActionGroup actionGroup;
        const auto action =poseHandler.IsReverse()? ActionType::BACKWARD_1_STEP_ACTION : ActionType::FORWARD_1_STEP_ACTION;
        const auto turnAction = poseHandler.IsReverse()? ActionType::REVERSE_TURNRIGHT_ACTION : ActionType::TURNRIGHT_ACTION;
        switch (poseHandler.carType) {
        case CarsType::CAR:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            break;
        case CarsType::SPORTS_CAR:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            actionGroup.PushAction(action);
            break;
        case CarsType::BUS:
            if (poseHandler.IsFast()) actionGroup.PushAction(action);
            actionGroup.PushAction(action);
            actionGroup.PushAction(turnAction);
            break;
        default:
            break;
        }
        return actionGroup;
    }
};

class FastCommand final 
{
public:
    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
    {
        ActionGroup actionGroup;
        actionGroup.PushAction(ActionType::BE_FAST_ACTION);
        return actionGroup;
    }
};

class ReverseCommand final 
{
public:
    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
        {
            ActionGroup actionGroup;
            actionGroup.PushAction(ActionType::BE_REVERSE_ACTION);
            return actionGroup;
        }
};

class TurnRoundCommand final
{
public:
    ActionGroup operator()(PoseHandler& poseHandler) const noexcept
    {   
        switch(poseHandler.carType){
            case CarsType::CAR:
                if (poseHandler.IsReverse()) return ActionGroup();
                if (poseHandler.IsFast()) {
                    return ActionGroup({ActionType::FORWARD_1_STEP_ACTION, ActionType::TURNLEFT_ACTION,
                    ActionType::FORWARD_1_STEP_ACTION, ActionType::TURNLEFT_ACTION});
                }
                return ActionGroup({ActionType::TURNLEFT_ACTION, ActionType::FORWARD_1_STEP_ACTION, ActionType::TURNLEFT_ACTION});
            case CarsType::SPORTS_CAR:
                return ActionGroup();
                break;
            case CarsType::BUS:
                return ActionGroup();
                break;
            default:
                return ActionGroup();
                break;
        }

        
    }
};

}  // namespace adas